<template>
  <a-drawer width="30%" placement="left" v-model:visible="isShow" :closable="false" @close="onClose">
    <a-descriptions title="基本信息" :column="2" layout="vertical" :bordered="true" size="small">
      <a-descriptions-item label="种子名称" :span="2">
        <p class="no-wrap">{{form.name}}</p>
      </a-descriptions-item>
      <a-descriptions-item label="添加时间" :span="2">
        <p class="no-wrap">{{formatDate(form.addtime)}}</p>
      </a-descriptions-item>
      <a-descriptions-item label="种子文件" :span="2">
        <a-space>
          <p class="no-wrap">{{form.torrentFile}}</p>
          <a-button v-if="form.torrentFile" shape="circle" size="small" @click="downloadTorrentFile(form.torrentFile)" :loading="downloading">
            <template #icon>
              <DownloadOutlined />
            </template>
          </a-button>
        </a-space>
      </a-descriptions-item>
      <a-descriptions-item label="下载链接" :span="2">
        <p class="no-wrap">{{form.address}}</p>
      </a-descriptions-item>
      <a-descriptions-item label="所属站点">
        <p class="no-wrap">{{form.siteName}}</p>
      </a-descriptions-item>
      <a-descriptions-item label="所属分类">
        <p class="no-wrap">{{form.categoryName}}</p>
      </a-descriptions-item>
      <a-descriptions-item label="描述" :span="2">
        <p class="no-wrap">{{form.description}}</p>
      </a-descriptions-item>
    </a-descriptions>
    <a-divider orientation="left" class="extra-title">下载信息<a-spin :spinning="loading" size="small" :style="{marginLeft: '5px'}" /></a-divider>
    <p v-if="!form.hashString">还未推送到下载器
      <a-button @click="toPush" shape="round">
        推送
      </a-button>
    </p>
    <a-collapse v-else v-model:activeKey="activeKey">
      <a-collapse-panel key="1" :header="info.client.name">
        <a-button @click="loadInfoInClient" shape="round" size="small" style="margin-right: 5px;" :loading="loading">
          刷新
        </a-button>
        <!-- 
        <PauseCircleOutlined v-if="autoRefresh" @click="stopAutoRefresh"/>
        <PlayCircleOutlined v-else @click="startAutoRefresh"/>
         -->
        <a-alert v-if="info.errorString" :message="info.errorString" type="error" show-icon/>
        <p>下载器：{{ info.client.type }} - {{ info.client.address }}</p>
        <p>添加时间：{{ formatDate(parseInt(info.addedDate)*1000) }}</p>
        <p>id：{{ info.id }}</p>
        <p>名称：{{ info.name }}</p>
        <p>HASH：{{ info.hashString }}</p>
        <p>下载位置：{{ info.downloadDir }}
          <a-button @click="toSetLocation" shape="round" size="small" >
            修改位置
          </a-button>
        </p>
        <p>总大小：{{ formatSize(info.totalSize) }} | 进度：{{ calRatio(info.totalSize - info.leftUntilDone, info.totalSize) }}</p> 
        <p>已完成：{{ formatSize(info.totalSize - info.leftUntilDone) }} | 下载速度：{{ formatSize(info.rateDownload) }}/s</p>
        <p>状态：{{ statusLabel[info.status] }}
          <a-button v-if="info.status===0" shape="circle" size="small" @click="doAction('start')" :loading="doActioning">
            <template #icon>
              <PlayCircleOutlined />
            </template>
          </a-button>
          <a-button v-else size="small" shape="circle" @click="doAction('stop')" :loading="doActioning">
            <template #icon>
              <PauseCircleOutlined />
            </template>
          </a-button>
        </p>
        <a-button @click="toLink" shape="round" size="small" >
          链接或移动到新的位置
        </a-button>
      </a-collapse-panel>
    </a-collapse>
  </a-drawer>

  <!-- 推送信息确认 -->
  <a-modal v-model:visible="pushShow" title="推送到下载器" okText="推送" @ok="doPush" :confirmLoading="pushLoading">
    <a-form ref="pushForm" :model="pushForm" :rule="pushRules" :label-col="labelCol" :wrapper-col="wrapperCol">
      <a-form-item label="下载器" name="clientid">
        <a-select
          v-model:value="pushForm.clientid"
        >
          <a-select-option v-for="option in clientOptions" :key="option.id" :value="option.id">
            {{ option.name }}
          </a-select-option>
        </a-select>
      </a-form-item>
      <a-form-item label="是否开始" name="startNow">
        <a-switch v-model:checked="pushForm.startNow" />
      </a-form-item>
      <a-form-item label="启用目录" >
        <a-checkbox v-model:checked="pushForm.enableSiteFolder">站点目录</a-checkbox>
        <a-checkbox v-model:checked="pushForm.enableCategoryFolder">分类目录</a-checkbox>
      </a-form-item>
    </a-form>
  </a-modal>

  <!-- 变更下载位置确认 -->
  <a-modal v-model:visible="setLocationShow" title="变更下载位置" okText="变更" @ok="doSetLocation" :confirmLoading="setLocationLoading">
    <a-form ref="setLocationForm" :model="setLocationForm" :rule="setLocationRules" :label-col="labelCol" :wrapper-col="wrapperCol">
      <a-form-item label="旧的位置">
        <span v-text="setLocationForm.olocation" />
      </a-form-item>
      <a-form-item label="新的位置" name="location">
        <a-input v-model:value="setLocationForm.location" />
      </a-form-item>
      <a-form-item label="移动文件" name="move">
        <a-switch v-model:checked="setLocationForm.move" />
      </a-form-item>
      <a-form-item label="进行校验" name="verify">
        <a-switch v-model:checked="setLocationForm.verify" />
      </a-form-item>
    </a-form>
  </a-modal>

  <!-- 链接到新的位置-->
  <a-drawer height="100%" placement="top" v-model:visible="linkShow" :closable="true" @close="linkClose">
    <a-alert
      message="说明："
      type="info"
      show-icon
    > 
      <template v-slot:icon><smile-outlined /></template>
      <template #description>
        <div>1.种子所在下载器与本系统部署在同一服务器；</div>
        <div>2.确认已配置无误：下载器-下载目录映射，基础配置-目录映射；</div>
        <div>3.慎用移动功能，将移动下载文件，影响做种；</div>
        <div>4.目前每次执行硬链接或移动都是本次的执行结果，不会保留之前的执行结果。</div>
      </template>
    </a-alert>
    <a-spin tip="处理中..." :spinning="linking">
      <a-row class="link-op-row">
        <a-col :span="12">
          <a-input  addon-before="原本目录：" v-model:value="linkInfo.sourceDir" disabled/>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="12">
          <a-input-group compact>
            <a-input addon-before="目标目录：" v-model:value="linkInfo.linkDir">
              <template #suffix>
                <FolderOpenOutlined @click="folderSelectShow=true"/>
              </template>
            </a-input>  
          </a-input-group>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="12">
          <a-input-group compact>
            <a-input
              addonBefore="将"
              v-model:value="replaceFrom"
              style=" width: 50%;"
              placeholder=""
              allowClear
            />
            <a-input-search
              addonBefore="替换为"
              v-model:value="replaceTo"
              style="width: 50%;"
              placeholder=""
              @search="doReplace"
              allowClear
            >
              <template v-slot:enterButton>
                <a-button type="primary">
                    文件名替换
                </a-button>
              </template>
            </a-input-search>
          </a-input-group>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="24">
          <a-space>
            <a-button type="primary" :loading="linking" @click="doLink(false)">
              硬链接
            </a-button>
            <a-button type="danger" :loading="linking" @click="toMove">
              移动
            </a-button>
          </a-space>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="24"><p style="margin:1em 0 0 0;">已选择 {{selectedLinkRowKeys.length}} 条，共 {{linkRows.length}} 条</p></a-col>
      </a-row>
      <a-table bordered :data-source="linkRows" :columns="linkRowsCols" rowKey="idx" :loading="linkInfoLoading"
        :row-selection="{ selectedRowKeys: selectedLinkRowKeys, onChange: onSelectLinkChange }"
        :pagination="false"
        size="small"
      >      
        <template #ratioCompleted="{ record }">
          {{ formatSize(record.bytesCompleted) }}({{ calRatio(record.bytesCompleted, record.length) }})
        </template> 
        <template #linkFile="{ record }">
          <a-input  v-model:value="record.linkFile">
            <template #suffix>
              <a-tooltip title="恢复为原文件名">
                <UndoOutlined @click="record.linkFile = record.sourceFile"/>
              </a-tooltip>
            </template>
          </a-input>
        </template>        
        <template v-slot:replace="{ record }">
          <a-switch checked-children="覆盖" un-checked-children="忽略" v-model:checked="record.replace" />
        </template>
        <template v-slot:status="{ record }">
          {{ linkRowStatus(record.status) }}
        </template>
      </a-table>
    </a-spin>
  </a-drawer>
  <!-- 路径选择 -->
  <a-modal v-model:visible="folderSelectShow" title="选择目录" @ok="linkDirChange">
    <FileSelector ref="refFileSelector"/>
  </a-modal>

</template>

<script>
import DateUtil from '../../utils/DateUtil.js'
import { downloadFile } from '../../utils/DownloadUtil'
import api from '../../api/api.js'
import TorrentApi from '../../api/TorrentApi.js'
import { SmileOutlined, PauseCircleOutlined, PlayCircleOutlined, FolderOpenOutlined, UndoOutlined, DownloadOutlined } from '@ant-design/icons-vue'
import { Modal } from 'ant-design-vue';
import FileSelector from '../components/FileSelector.vue'
import { ref } from 'vue';
//<script setup> : https://github.com/vuejs/rfcs/blob/script-setup-2/active-rfcs/0000-script-setup.md
export default {
  name: 'TorrentDetail',
  components: {
    SmileOutlined,
    PauseCircleOutlined,
    PlayCircleOutlined,
    FileSelector,
    FolderOpenOutlined,
    UndoOutlined,
    DownloadOutlined
  },
  props: {
    siteOptions: {
      type: Array,
      default: []
    },
    categoryOptions: {
      type: Array,
      default: []
    },
    clientOptions: {
      type: Array,
      default: []
    },
    libraryOptions: {
      type: Array,
      default: []
    },
  },
  setup() {
    const refFileSelector = ref()
    const folderSelected = () => {
      return refFileSelector.value.selectedKeys
    }
    return {
      refFileSelector, folderSelected
    }
  },
  data() {
    return {
      module: 'torrent',
      isShow: false,loading:false,activeKey:['1'],
      form: {
      },
      statusLabel:{
        "-1": "All",
        "0": "Stopped",
        "1": "Check waiting",
        "2": "Checking",
        "3": "Download waiting",
        "4": "Downloading",
        "5": "Seed waiting",
        "6": "Seeding",
      },
      autoRefresh: null,
      info: {
        client:{}
      },
      labelCol: { span: 5 },
      wrapperCol: { span: 19 },
      pushShow: false,pushLoading: false,
      pushForm: {},
      pushRules: {
        clientid: [
          { required: true, message: '请选择下载器', trigger: 'change' },
        ],
      },
      setLocationShow: false,setLocationLoading: false,
      setLocationForm: {},
      setLocationRules: {
        location: [
          { required: true, message: '请填写新的位置', trigger: 'blur' },
        ],
      },
      linkShow: false,linking: false,
      linkInfo:{},linkInfoLoading: false,folderSelectShow: false,
      linkRows: [],selectedLinkRowKeys: [],
      linkRowsCols: [
        {
          title: '序号',
          fixed: 'left',
          width: 80,
          customRender: ({ index })=>`${index+1}`,
        },
        {
          title: '已下载',
          width: 200,
          slots: { customRender: 'ratioCompleted' },
        },
        {
          title: '文件名（可以包含路径）',
          dataIndex: 'linkFile',
          slots: { customRender: 'linkFile' },
        },
        {
          title: '如目标存在',
          dataIndex: 'replace',
          width: 100,
          align: 'center',
          slots: { customRender: 'replace' },
        },
        {
          title: '状态',
          key: 'status',
          fixed: 'right',
          width: 200,
          slots: { customRender: 'status' },
        },
      ],
      linkFolder:'',replaceFrom: '',replaceTo: '',
      downloading: false,doActioning: false
    }
  },
  methods: {
    formatDate(val) {
      return DateUtil.formatTimestamp(val)
    },
    calRatio(a, total) {
      let temp = a/total*100
      return temp.toFixed(2) + '%'
    },
    formatSize(val) {
      let temp = parseFloat(val) // byte
      if (temp < 1024) return temp.toFixed(2) + "B"
      temp = temp/1024  //kb
      if (temp < 1024) return temp.toFixed(2) + "KB"    
      temp = temp/1024 //mb
      if (temp < 1024) return temp.toFixed(2) + "MB" 
      temp = temp/1024 //gb
      if (temp < 1024) return temp.toFixed(2) + "GB"
      temp = temp/1024 //tb
      if (temp < 1024) return temp.toFixed(2) + "TB"
      temp = temp/1024 //pb
      return temp.toFixed(2) + "PB"
    },
    open(form) {
        this.pushForm = {
          id: '',
          clientid: '',
          startNow: false,
        }
        this.form = form
        this.info = {
          client:{}
        }
        this.loadInfoInClient()
        this.isShow = true
        // this.startAutoRefresh()
    },
    onClose() {
      // this.activeKey = []
      this.stopAutoRefresh()
    },
    startAutoRefresh() {
      if (this.autoRefresh)return
      this.autoRefresh = setInterval(() => {
        this.loadInfoInClient()
      }, 5000);
    },
    stopAutoRefresh() {
      if (!this.autoRefresh)return
      clearInterval(this.autoRefresh)
      this.autoRefresh = null
    },
    loadInfoInClient() {
      if (!this.form.hashString) return
      this.loading = true 
      TorrentApi.infoInClient({id: this.form.id}).then(response => {
        if (response.data.code === 1) {
          if (response.data.data) 
            this.info = response.data.data
        } else {
          this.stopAutoRefresh()
          this.$message.error(`数据加载失败：${response.data.message}`)
        }
      }).then(()=>{
        this.loading = false 
      })
    },
    async downloadTorrentFile(file) {
      this.downloading = true
      const downloadObj = await api.download({name:file, type: 'torrent'});
      this.downloading = false
      // console.log(downloadObj)
      downloadFile(downloadObj.data, file)
    },
    toPush() {
      this.pushForm.id = this.form.id
      this.pushForm.clientid = this.form.clientid
      this.pushForm.startNow = false
      this.pushForm.enableSiteFolder = true
      this.pushForm.enableCategoryFolder = true
      this.pushShow = true
    },
    doPush() {
      this.$refs.pushForm
      .validate()
      .then(() => {
        this.pushLoading = true
        TorrentApi.pushToClient(this.pushForm).then(response => {
          if (response.data.code === 1) {
            this.form.hashString = response.data.data.hashString
            // this.info = response.data.data
            this.loadInfoInClient()
            this.pushShow = false
            this.$message.success('推送成功')
          } else {
            this.$message.error(`推送失败：${response.data.message}`)
          }
        }).catch((error)=>{
          this.$message.error(`推送失败：${error.message}`)
        }).then(()=>{
          this.pushLoading = false
        })
      })
      .catch(error => {
        // console.log('error', error);
      })
    },
    linkClose() {
      this.linkInfo = {}
      this.linkRows = [],
      this.selectedLinkRowKeys = []
      this.linkFolder = ''
      this.replaceFrom = ''
      this.replaceTo = ''
    },
    toLink() {
      this.linkShow = true
      if(this.linking || this.linkInfoLoading)return // 正在处理
      this.linkInfoLoading = true
      TorrentApi.linkToLibrary({id: this.form.id}).then(response=>{
        if (response.data.code === 1) {
          this.linkInfo.torrentId = this.form.id,
          this.linkInfo.sourceDir = response.data.data.sourceDir
          this.linkRows = response.data.data.files.map((file,index)=>{
            return {
              idx: index,
              sourceFile: file.name,
              linkFile: file.name,
              bytesCompleted: file.bytesCompleted,
              length: file.length,
              replace: false,
              status: 0
            }
          })
        } else {
          this.$message.error(`${response.data.message}`)
        }
      }).then(()=>{
        this.linkInfoLoading = false
      })
    },
    linkRowStatus(status) {
      if (status === 0)
        return '未执行' 
      else if (status === 1)
        return '成功'
      else if (status === 201)
        return '原文件不存在'
      else if (status === 202)
        return '目标文件已存在'
      else 
        return '未知'  
    },
    doReplace() {
      if (this.replaceFrom) {
        this.linkRows.forEach(r => {
          r.linkFile = r.linkFile.replace(this.replaceFrom,this.replaceTo)
        })
      }
    },
    onSelectLinkChange(selectedRowKeys) {
      // console.log('selectedRowKeys changed: ', selectedRowKeys);
      this.selectedLinkRowKeys = selectedRowKeys;
    },
    linkDirChange() {
      this.linkInfo.linkDir = this.folderSelected()[0]
      this.folderSelectShow = false
    },
    toMove() {
      const that = this
      Modal.confirm({
        title: '请确认自己在做什么',
        content: '移动文件会影响做种！移动前会自动暂停种子。',
        okText: '继续',
        cancelText: '取消',
        onOk() {
          that.doLink(true)
        }
      });
    },
    doLink(move) {
      this.linking = true
      if (!this.linkInfo.linkDir) {
        this.$message.warn("请指定目标目录")
        this.linking = false
        return
      }
      if (this.selectedLinkRowKeys.length === 0) {
        this.linking = false
        this.$message.warn("请选择需要操作的文件")
        return
      }
      // 哪些需要进行链接
      this.linkRows.forEach(linkRow => {
        linkRow.selected = false
        linkRow.status = 0
      })
      this.selectedLinkRowKeys.forEach(index => {
        this.linkRows[index].selected = true
      })
      // 开始
      TorrentApi.doLinkToLibrary(
        {
          ...this.linkInfo,
          linkRows: this.linkRows,
          move: move
        }
      ).then(response=>{
        if (response.data.code === 1) {
          this.linkRows = response.data.data
          this.$message.success('操作完成，执行结果请查看列表')
        } else {
          this.$message.error(`操作失败：${response.data.message}`)
        }
      }).catch((error)=>{
        this.$message.error(`操作失败：${error.message}`)
      }).then(()=>{
        this.linking = false
      })
    },
    toSetLocation() {
      const site = this.siteOptions.find(o => o.id === this.form.siteid)
      const category = this.categoryOptions.find(o => o.id === this.form.categoryid)
      this.setLocationForm.id = this.form.id
      this.setLocationForm.olocation = this.info.downloadDir
      this.setLocationForm.location = this.info.baseDownlaodPath + (site?'/'+site.folder:'') + (category?'/'+category.folder:'')
      this.setLocationForm.move = true
      this.setLocationForm.verify = true
      this.setLocationShow = true
    },
    doSetLocation() {
      this.$refs.setLocationForm
      .validate()
      .then(() => {
        this.setLocationLoading = true
        TorrentApi.setLocation(this.setLocationForm).then(response => {
          if (response.data.code === 1) {
            this.loadInfoInClient()
            this.setLocationShow = false
            this.$message.success('变更成功')
          } else {
            this.$message.error(`变更失败：${response.data.message}`)
          }
        }).catch((error)=>{
          this.$message.error(`变更失败：${error.message}`)
        }).then(()=>{
          this.setLocationLoading = false
        })
      })
      .catch(error => {
        // console.log('error', error);
      })
    },
    doAction(action) {
      if (!this.form.id && !action) return
      this.doActioning = true
      TorrentApi.doAction(this.form.id, action).then(response => {
        if (response.data.code === 1) {
          setTimeout(()=>{
            this.loadInfoInClient()
            this.$message.success('操作成功')
            this.doActioning = false
          }, 3000)
        } else {
          this.doActioning = false
          this.$message.error(`操作失败：${response.data.message}`)
        }
      }).catch((error)=>{
        this.doActioning = false
        this.$message.error(`操作失败：${error.message}`)
      })
    }
  }
}
</script>
<style scoped>
.no-wrap{
  overflow-wrap: anywhere;
  margin: 0px;
}
.extra-title {
  color: gray;
  font-size: 14px;
  font-weight: 300;
}
.link-op-row {
  margin: 10px 0;
}
</style>>